# 解决不同形状数组之间的算术运算问题
import numpy as np

# 如果进行运算的两个数组形状完全相同，它们直接可以做相应的运算
a = np.array([0.1, 0.2, 0.3, 0.4])
b = np.array([10, 20, 30, 40])
c = a * b
print(c)  # [ 1.  4.  9.  16.]

# 当进行运算的两个数组形状不同，Numpy 会自动触发广播机制
a = np.array([[0, 0, 0],
              [10, 10, 10],
              [20, 20, 20],
              [30, 30, 30]])
# b数组与a数组形状不同
b = np.array([1, 2, 3])
print(a + b)
# [[ 1  2  3]
# [11 12 13]
# [21 22 23]
# [31 32 33]]
# 4x3 的二维 a 数组 与 1x3 的一维 b 数组相加，
# 本质上可以理解为 b 数组第一行重复 3 次，从而生成与 a 数组相同形状的数组后再与 a 数组进行运算


# NumPy遍历数组
# NumPy 提供了一个 nditer 迭代器对象，它可以配合 for 循环完成对数组元素的遍历。
a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
# 使用nditer迭代器,并使用for进行遍历
for x in np.nditer(a):
    print(x)  # 0 5 10 15 20 25 30 35 40 45 50 55

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
b = a.T  # a的转置数组
print(b)
# [[ 0 20 40]
# [ 5 25 45]
# [10 30 50]
# [15 35 55]]
for x in np.nditer(b):
    print(x, end=",")  # 0,5,10,15,20,25,30,35,40,45,50,55,

print()
for x in np.nditer(a.T.copy(order='C')):
    print(x, end=", ")  # 0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,
# a.T.copy(order = 'C') 的遍历结果与示例 1、2 的数组遍历结果不一样。究其原因，就是因为它们在内存中的存储方式不一样。
print()

# 指定遍历顺序
for x in np.nditer(a, order='C'):
    print(x, end=",")  # 0,5,10,15,20,25,30,35,40,45,50,55,
print()
for x in np.nditer(a, order='F'):
    print(x, end=",")  # 0,20,40,5,25,45,10,30,50,15,35,55,

print()
# 修改数组元素值 nditer 对象提供了一个可选参数op_flags，它表示能否在遍历数组时对元素进行修改。
# read-only 只读模式，在这种模式下，遍历时不能修改数组中的元素
# read-write 读写模式，遍历时可以修改元素值。
# write-only 只写模式，在遍历时可以修改元素值。
print("原数组是: \n", a)
# [[ 0  5 10 15]
# [20 25 30 35]
# [40 45 50 55]]
for x in np.nditer(a, op_flags=['readwrite']):
    x[...] = 2 * x
print("修改后的数组是： \n", a)
# [[ 0  10  20  30]
# [ 40  50  60  70]
# [ 80  90 100 110]]

# 迭代多个数组
# 如果两个数组都能够被广播，那么 nditer 对象就可以同时对它们迭代。
a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print(a)
# [[ 0  5 10 15]
#  [20 25 30 35]
#  [40 45 50 55]]
b = np.array([1, 2, 3, 4], dtype=int)
print(b)
# [1 2 3 4]
# 广播迭代
for x, y in np.nditer([a, b]):
    print("%d:%d" % (x, y), end=",")
# 0:1,5:2,10:3,15:4,20:1,25:2,30:3,35:4,40:1,45:2,50:3,55:4,
